package com.zhy.generator.codegen.mybatis.javacontroller;

import com.zhy.generator.codegen.api.CommentGenerator;
import com.zhy.generator.codegen.dom.java.*;
import com.zhy.generator.codegen.mybatis.AbstractJavaGenerator;
import com.zhy.generator.codegen.mybatis.javacontroller.elements.*;
import com.zhy.generator.config.Configuration;
import com.zhy.generator.config.ConfigurationConstant;

import java.util.ArrayList;
import java.util.List;

import static cn.hutool.core.util.StrUtil.isNotBlank;
import static com.zhy.generator.codegen.util.JavaBeansUtil.getCamelCaseString;
import static com.zhy.generator.codegen.util.Messages.getString;

/**
 * @author 源
 */
public class JavaControllerGenerator extends AbstractJavaGenerator {
    @Override
    public List<CompilationUnit> getCompilationUnits() {

        progressCallback.startTask(getString("Progress.15", introspectedTable.getFullyQualifiedTable()));
        CommentGenerator commentGenerator = context.getCommentGenerator();

        Configuration configuration = context.getConfiguration(ConfigurationConstant.CONFIGURATION_CONTROLLER);

        FullyQualifiedJavaType type = new FullyQualifiedJavaType(introspectedTable.getControllerType());
        TopLevelClass tlc = new TopLevelClass(type);
        tlc.setVisibility(JavaVisibility.PUBLIC);
        commentGenerator.addJavaFileComment(tlc);

        tlc.addImportedType(getApiStatusType());
        tlc.addImportedType(getReturnType());
        tlc.addImportedType(getResultUtilType());

        String rootClass = configuration.getRootClass();
        FullyQualifiedJavaType rootClassType = new FullyQualifiedJavaType(rootClass);

        tlc.setSuperClass(rootClassType);
        tlc.addImportedType(rootClassType);

        tlc.addAnnotation("@RestController");
        tlc.addAnnotation("@RequestMapping(value = \"" + getMappingPath(configuration) + "\")");
        tlc.addAnnotation("@Api(tags = \"" + introspectedTable.getRemarks() + "\")");

        tlc.addImportedType("org.springframework.web.bind.annotation.RestController");
        tlc.addImportedType("org.springframework.web.bind.annotation.RequestMapping");
        tlc.addImportedType("io.swagger.annotations.Api");

        Field serviceField = new Field();
        FullyQualifiedJavaType serviceType = new FullyQualifiedJavaType(introspectedTable.getServiceType());
        serviceField.setType(serviceType);
        serviceField.setName(getCamelCaseString(serviceType.getShortName(), false));
        serviceField.addAnnotation("@Autowired");
        serviceField.setVisibility(JavaVisibility.PRIVATE);
        tlc.addField(serviceField);
        tlc.addImportedType("org.springframework.beans.factory.annotation.Autowired");
        tlc.addImportedType(serviceType);

        addListMethodGenerator(tlc);
        addGetMethodGenerator(tlc);
        addAddMethodGenerator(tlc);
        addEditMethodGenerator(tlc);
        addDelMethodGenerator(tlc);
        List<CompilationUnit> answer = new ArrayList<CompilationUnit>();
        answer.add(tlc);

        return answer;
    }

    private void addDelMethodGenerator(TopLevelClass tlc) {
        AbstractJavaControllerMethodGenerator generator = new DelMethodGenerator();
        initializeAndExecuteGenerator(generator, tlc);
    }

    private void addEditMethodGenerator(TopLevelClass tlc) {
        AbstractJavaControllerMethodGenerator generator = new EditMethodGenerator();
        initializeAndExecuteGenerator(generator, tlc);
    }

    private void addAddMethodGenerator(TopLevelClass tlc) {
        AbstractJavaControllerMethodGenerator generator = new AddMethodGenerator();
        initializeAndExecuteGenerator(generator, tlc);
    }

    private void addGetMethodGenerator(TopLevelClass tlc) {
        AbstractJavaControllerMethodGenerator generator = new GetMethodGenerator();
        initializeAndExecuteGenerator(generator, tlc);
    }

    private void addListMethodGenerator(TopLevelClass tlc) {
        AbstractJavaControllerMethodGenerator generator = new ListMethodGenerator();
        initializeAndExecuteGenerator(generator, tlc);
    }

    protected void initializeAndExecuteGenerator(AbstractJavaControllerMethodGenerator methodGenerator, TopLevelClass tlc) {
        methodGenerator.setContext(context);
        methodGenerator.setIntrospectedTable(introspectedTable);
        methodGenerator.setProgressCallback(progressCallback);
        methodGenerator.setWarnings(warnings);
        methodGenerator.addControllerElements(tlc);
    }

    private String getMappingPath(Configuration configuration) {
        String mappingPath = configuration.getMappingPath();
        StringBuffer sb = new StringBuffer();

        if (isNotBlank(mappingPath)) {
            sb.append("/").append(mappingPath);
        }

        String subPackage = introspectedTable.getSubPackage();

        if (isNotBlank(subPackage)) {
            subPackage = subPackage.replaceAll("\\.", "");
            sb.append("/").append(subPackage);
        }
        sb.append("/").append(introspectedTable.getDomainObjectName());

        return sb.toString();
    }


    private FullyQualifiedJavaType getApiStatusType() {
        return new FullyQualifiedJavaType(JavaControllerMethodConstant.RESULT_ERRORCODE);
    }

    private FullyQualifiedJavaType getReturnType() {
        return new FullyQualifiedJavaType(JavaControllerMethodConstant.RESULT_RESPONSE);
    }

    private FullyQualifiedJavaType getResultUtilType() {
        return new FullyQualifiedJavaType(JavaControllerMethodConstant.RESULT_UTIL);
    }
}
